home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 23
/
AACD 23.iso
/
AACD
/
Online
/
opennap
/
browse.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-08
|
9KB
|
429 lines
/* Copyright (C) 2000-1 drscholl@users.sourceforge.net
This is free software distributed under the terms of the
GNU Public License. See the file COPYING for details.
$Id: browse.c,v 1.46 2001/02/15 08:39:45 drscholl Exp $ */
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "opennap.h"
#include "debug.h"
#ifndef ROUTING_ONLY
typedef struct
{
short count;
short max;
USER *sender;
USER *user;
}
BROWSE;
static void
browse_callback (DATUM * info, BROWSE * ctx)
{
/* avoid flooding the client */
if (ctx->max == 0 || ctx->count < ctx->max)
{
send_user (ctx->sender, MSG_SERVER_BROWSE_RESPONSE,
"%s \"%s\" %s %u %hu %hu %hu",
info->user->nick, info->filename,
#if RESUME
info->hash,
#else
"00000000000000000000000000000000",
#endif
info->size,
BitRate[info->bitrate], SampleRate[info->frequency],
info->duration);
ctx->count++;
}
}
#endif /* ! ROUTING_ONLY */
/* 211 [ :<sender> ] <nick> [ <max> ]
browse a user's files */
HANDLER (browse)
{
USER *sender, *user;
char *nick;
int result;
(void) tag;
(void) len;
ASSERT (validate_connection (con));
if (pop_user (con, &pkt, &sender))
return;
nick = next_arg (&pkt);
if (!nick)
{
unparsable (con);
return;
}
if (invalid_nick (nick))
{
invalid_nick_msg (con);
return;
}
user = hash_lookup (Users, nick);
if (!user)
{
if (ISUSER (con))
{
/* the napster servers send a 210 instead of 404 for this case */
send_cmd (con, MSG_SERVER_USER_SIGNOFF, "%s", nick);
/* always terminate the list */
send_cmd (con, MSG_SERVER_BROWSE_END, "%s", nick);
}
return;
}
ASSERT (validate_user (user));
if (pkt)
{
result = atoi (pkt);
if (Max_Browse_Result > 0 && result > Max_Browse_Result)
result = Max_Browse_Result;
}
else
result = Max_Browse_Result;
if (!option (ON_REMOTE_BROWSE) &&
(!ISUSER (sender->con) || !ISUSER (user->con)))
{
/* remote browsing is not supported */
send_user (sender, MSG_SERVER_BROWSE_END, "%s %u",
user->nick, (user->shared > 0) ? user->ip : 0);
return;
}
if (ISUSER (user->con))
{
#ifndef ROUTING_ONLY
if (user->con->uopt->files)
{
BROWSE data;
data.count = 0;
data.user = user;
data.sender = sender;
data.max = pkt ? atoi (pkt) : 0;
if (Max_Browse_Result > 0 && data.max > Max_Browse_Result)
data.max = Max_Browse_Result;
hash_foreach (user->con->uopt->files,
(hash_callback_t) browse_callback, &data);
}
#endif /* ! ROUTING_ONLY */
/* send end of browse list message */
send_user (sender, MSG_SERVER_BROWSE_END, "%s %u", user->nick,
/* don't send the ip if the user isn't sharing - security */
user->shared > 0 ? user->ip : 0);
}
else
{
/* relay to the server that this user is connected to */
send_cmd (user->con, tag, ":%s %s %d", sender->nick, user->nick,
result);
}
}
/* deprecated - clients should do direct browsing with 640 now. this was
* causing too much cpu use for users with large amounts of shared files
*/
#if 0
#ifndef ROUTING_ONLY
static void
create_file_list (DATUM * d, LIST ** p)
{
DATUM *f;
while (*p)
{
f = (*p)->data;
if (strcasecmp (d->filename, f->filename) <= 0)
{
LIST *n = CALLOC (1, sizeof (LIST));
n->data = d;
n->next = *p;
*p = n;
return;
}
p = &(*p)->next;
}
*p = CALLOC (1, sizeof (LIST));
(*p)->data = d;
}
static char *
last_slash (char *s)
{
/* const */ char *p;
for (;;)
{
p = strpbrk (s + 1, "/\\");
if (!p)
return s;
s = p;
}
}
static char *
dirname (char *d, int dsize, /* const */ char *s)
{
char *p;
strncpy (d, s, dsize - 1);
d[dsize - 1] = 0;
p = last_slash (d);
*p = 0;
return d;
}
static char *
my_basename (char *d, int dsize, /* const */ char *s)
{
s = last_slash (s);
strncpy (d, s + 1, dsize - 1);
d[dsize - 1] = 0;
return d;
}
#endif /* ! ROUTING_ONLY */
/* 10301 [ :<sender> ] <nick>
new browse requst */
HANDLER (browse_new)
{
USER *sender, *user;
char *nick;
int results = -1;
(void) len;
ASSERT (validate_connection (con));
if (pop_user (con, &pkt, &sender))
return;
nick = next_arg (&pkt);
if (!nick)
{
unparsable (con);
return;
}
user = hash_lookup (Users, nick);
if (!user)
{
if (ISUSER (con))
send_cmd (con, MSG_SERVER_NOSUCH, "browse failed: no such user");
send_user (sender, tag, "%s 0", nick); /* always terminate */
return;
}
if (pkt)
{
results = atoi (pkt);
if (Max_Browse_Result > 0 && results > Max_Browse_Result)
results = Max_Browse_Result;
}
else
results = Max_Browse_Result;
if (ISUSER (user->con))
{
#ifndef ROUTING_ONLY
if (user->con->uopt->files)
{
LIST *list = 0, *tmpList;
char dir[_POSIX_PATH_MAX];
char path[_POSIX_PATH_MAX];
char base[_POSIX_PATH_MAX];
char *rsp = 0;
int count = 0;
hash_foreach (user->con->uopt->files,
(hash_callback_t) create_file_list, &list);
dir[0] = 0;
if (results == 0)
results = 0x7fffffff; /* hack, we really mean unlimited */
for (tmpList = list; tmpList && results;
tmpList = tmpList->next, results--)
{
DATUM *d = tmpList->data;
dirname (path, sizeof (path), d->filename);
my_basename (base, sizeof (base), d->filename);
if (count < 5 && dir[0] && !strcasecmp (dir, path))
{
/* same directory as previous result, append */
rsp = append_string (rsp, " \"%s\" %s %u %d %d %d", base,
#if RESUME
d->hash,
#else
"0",
#endif
d->size,
BitRate[d->bitrate],
SampleRate[d->frequency],
d->duration);
if (!rsp)
break;
count++;
}
else
{
/* new directory */
strcpy (dir, path);
if (rsp)
{
/* send off the previous buffer command */
send_user (sender, MSG_SERVER_BROWSE_RESULT_NEW, "%s",
rsp);
FREE (rsp);
}
rsp = append_string (0, "%s \"%s\" \"%s\" %s %u %d %d %d",
user->nick, dir, base,
#if RESUME
d->hash,
#else
"0",
#endif
d->size,
BitRate[d->bitrate],
SampleRate[d->frequency],
d->duration);
if (!rsp)
break;
count = 0;
}
}
list_free (list, 0);
if (rsp)
{
send_user (sender, MSG_SERVER_BROWSE_RESULT_NEW, "%s", rsp);
FREE (rsp);
}
}
#endif /* ! ROUTING_ONLY */
/* terminate the list */
send_user (sender, tag, "%s %u", user->nick,
/* don't give out ip if not sharing anything - security */
user->shared > 0 ? user->ip : 0);
}
else
{
/* relay the request to the server where this user is connected */
send_cmd (user->con, tag, ":%s %s %d", sender->nick, user->nick,
results);
}
}
#endif
/* 640 [:sender] nick
* direct browse request
*/
HANDLER (browse_direct)
{
char *sender_name, *nick;
USER *sender, *user;
(void) len;
if (pop_user_server (con, tag, &pkt, &sender_name, &sender))
return;
nick = next_arg (&pkt);
if (!nick)
{
unparsable (con);
return;
}
user = hash_lookup (Users, nick);
if (!user)
{
nosuchuser (con);
return;
}
if (ISUSER (con))
{
if (sender->port == 0 && user->port == 0)
{
send_cmd (con, MSG_SERVER_BROWSE_DIRECT_ERR,
"%s \"Both you and %s are firewalled; you cannot browse or download from them.\"",
user->nick, user->nick);
return;
}
else if (user->shared == 0)
{
send_cmd (con, MSG_SERVER_BROWSE_DIRECT_ERR,
"%s \"%s is not sharing any files.\"",
user->nick, user->nick);
return;
}
}
if (ISUSER (user->con))
{
if (!is_ignoring (user->con->uopt->ignore, sender->nick))
{
if (user->port == 0)
{
/* client being browsed is firewalled. send full info so
* a back connection to the browser can be made.
*/
send_cmd (user->con, MSG_CLIENT_BROWSE_DIRECT, "%s %u %hu",
sender_name, sender->ip, sender->port);
}
else
{
/* directly connected to this server */
send_cmd (user->con, MSG_CLIENT_BROWSE_DIRECT, "%s",
sender_name);
}
}
else
send_cmd (con, MSG_SERVER_BROWSE_DIRECT_ERR,
"%s \"%s is not online.\"", user->nick, user->nick);
}
else
send_cmd (user->con, MSG_CLIENT_BROWSE_DIRECT, ":%s %s", sender_name,
user->nick);
}
/* 641 [:sender] nick
* direct browse accept
*/
HANDLER (browse_direct_ok)
{
char *sender_name, *nick;
USER *sender, *user;
(void) len;
if (pop_user_server (con, tag, &pkt, &sender_name, &sender))
return;
nick = next_arg (&pkt);
if (!nick)
{
unparsable (con);
return;
}
user = hash_lookup (Users, nick);
if (!user)
{
nosuchuser (con);
return;
}
if (ISUSER (user->con))
{
/* directly connected to this server */
send_cmd (user->con, MSG_SERVER_BROWSE_DIRECT_OK, "%s %u %hu",
sender->nick, sender->ip, sender->port);
}
else
send_cmd (user->con, MSG_SERVER_BROWSE_DIRECT_OK, ":%s %s",
sender_name, user->nick);
}